package com.tankbattle.model;

import com.tankbattle.util.ImageManager;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.Color;

/**
 * 坦克类，继承自GameObject
 */
public class Tank extends GameObject {
    private Direction direction;  // 当前方向
    private double speed;        // 当前速度
    private final double maxSpeed;     // 最大速度
    private final double acceleration; // 加速度
    private final double deceleration; // 减速度
    private boolean moving;      // 是否正在移动
    private final boolean player;      // 是否为玩家坦克
    private int health;          // 坦克生命值
    private final int maxHealth;       // 最大生命值
    private long lastFireTime;   // 上次开火时间
    private final int fireRate;        // 开火频率（毫秒）
    private int oldX, oldY;
    private Tank playerTank; // 玩家坦克的引用
    private long lastDirectionChangeTime; // 上次改变方向的时间
    private static final int DIRECTION_CHANGE_INTERVAL = 2000; // 改变方向的间隔时间（毫秒）
    private static final int DETECTION_RANGE = 300; // 检测玩家的范围

    public Tank(int x, int y, Direction direction, boolean player) {
        super(x, y, 48, 48);
        this.direction = direction;
        this.player = player;
        this.maxSpeed = player ? 5.0 : 2.0; // 降低敌人移动速度
        this.speed = 0;
        this.acceleration = 0.3;
        this.deceleration = 0.2;
        this.moving = false;
        this.maxHealth = player ? 5 : 2; // 玩家坦克5点血量，敌方坦克2点血量
        this.health = this.maxHealth;
        this.fireRate = player ? 500 : 2000;
        this.lastFireTime = 0;
        this.oldX = x;
        this.oldY = y;
        this.lastDirectionChangeTime = System.currentTimeMillis();
    }

    public void setPlayerTank(Tank playerTank) {
        this.playerTank = playerTank;
    }

    private boolean canSeePlayer() {
        if (playerTank == null || !playerTank.isActive()) return false;

        // 计算与玩家的距离
        int dx = playerTank.getX() - this.x;
        int dy = playerTank.getY() - this.y;
        double distance = Math.sqrt(dx * dx + dy * dy);

        if (distance > DETECTION_RANGE) return false;

        // 检查是否在同一直线上
        boolean inLine = false;
        switch (this.direction) {
            case UP:
                inLine = Math.abs(dx) < 24 && dy < 0;
                break;
            case DOWN:
                inLine = Math.abs(dx) < 24 && dy > 0;
                break;
            case LEFT:
                inLine = Math.abs(dy) < 24 && dx < 0;
                break;
            case RIGHT:
                inLine = Math.abs(dy) < 24 && dx > 0;
                break;
        }
        return inLine;
    }

    @Override
    public void update(double delta) {
        if (!player && isActive()) {
            updateEnemyBehavior();
        }

        oldX = x;
        oldY = y;

        if (moving) {
            speed = Math.min(speed + acceleration, maxSpeed);
        } else {
            speed = Math.max(0, speed - deceleration);
        }

        if (speed > 0) {
            switch (direction) {
                case UP:
                    y = (int)(y - speed);
                    break;
                case RIGHT:
                    x = (int)(x + speed);
                    break;
                case DOWN:
                    y = (int)(y + speed);
                    break;
                case LEFT:
                    x = (int)(x - speed);
                    break;
            }
        }
    }

    private void move() {
        switch (direction) {
            case UP:
                y -= speed;
                break;
            case DOWN:
                y += speed;
                break;
            case LEFT:
                x -= speed;
                break;
            case RIGHT:
                x += speed;
                break;
        }
    }

    private void updateEnemyBehavior() {
        if (playerTank == null || !playerTank.isActive()) return;

        long currentTime = System.currentTimeMillis();

        // 检测玩家并尝试瞄准
        if (canSeePlayer()) {
            // 如果看到玩家就开火
            moving = false;
            fire();
        } else {
            // 随机移动
            if (currentTime - lastDirectionChangeTime > DIRECTION_CHANGE_INTERVAL) {
                // 随机改变方向
                Direction[] directions = Direction.values();
                direction = directions[(int)(Math.random() * directions.length)];
                moving = Math.random() > 0.3; // 70%的概率会移动
                lastDirectionChangeTime = currentTime;
            }
        }
    }

    /**
     * 检查坦克是否超出屏幕边界
     * @param screenWidth 屏幕宽度
     * @param screenHeight 屏幕高度
     */
    public void checkBounds(int screenWidth, int screenHeight) {
        if (x < 0) x = 0;
        if (y < 0) y = 0;
        if (x > screenWidth - width) x = screenWidth - width;
        if (y > screenHeight - height) y = screenHeight - height;
    }

    /**
     * 当发生碰撞时，将坦克位置恢复到移动前的位置
     */
    public void revertPosition() {
        x = oldX;
        y = oldY;
    }

    /**
     * 检查是否可以开火
     * @return 如果可以开火返回true，否则返回false
     */
    public boolean canFire() {
        long currentTime = System.currentTimeMillis();
        return currentTime - lastFireTime >= fireRate;
    }

    /**
     * 开火，创建一个子弹对象
     * @return 创建的子弹对象
     */
    public Bullet fire() {
        long currentTime = System.currentTimeMillis();
        if (currentTime - lastFireTime < fireRate) {
            return null;
        }
        
        lastFireTime = currentTime;

        // 计算子弹的生成位置
        int bulletX = x + width / 2 - 8; // 子弹宽度的一半
        int bulletY = y + height / 2 - 8; // 子弹高度的一半

        return new Bullet(bulletX, bulletY, direction, player);
    }

    /**
     * 坦克受到伤害
     * @return 如果坦克被摧毁返回true，否则返回false
     */
    public boolean takeDamage() {
        health--;
        return health <= 0;
    }

    @Override
    public void draw(Graphics2D g) {
        if (!active) return;

        // 根据坦克类型和方向获取对应图片
        String imageKey;
        if (player) {
            imageKey = "player_tank_" + direction.toString().toLowerCase() + ".png";
        } else {
            imageKey = "tank_" + direction.toString().toLowerCase() + ".png";
        }
        BufferedImage tankImage = ImageManager.getInstance().getImage(imageKey);
        if (tankImage != null) {
            g.drawImage(tankImage, x, y, width, height, null);
        }

        // 绘制血条
        int healthBarWidth = 40;
        int healthBarHeight = 4;
        int healthBarX = x + (width - healthBarWidth) / 2;
        int healthBarY = y - 10;  // 血条位置在坦克上方

        // 绘制血条背景（灰色）
        g.setColor(new Color(80, 80, 80));
        g.fillRect(healthBarX, healthBarY, healthBarWidth, healthBarHeight);

        // 绘制当前血量（红色）
        g.setColor(new Color(255, 0, 0));
        int currentHealthWidth = (int)((float)health / maxHealth * healthBarWidth);
        g.fillRect(healthBarX, healthBarY, currentHealthWidth, healthBarHeight);

        // 绘制血条边框
        g.setColor(Color.BLACK);
        g.drawRect(healthBarX, healthBarY, healthBarWidth, healthBarHeight);
    }

    /**
     * 获取坦克的碰撞边界
     * 返回一个略小于实际大小的矩形，使碰撞检测更精确
     */
    public Rectangle getCollisionBounds() {
        // 碰撞区域比实际图像小一些，这样更容易通过狭窄通道
        int padding = 4;
        return new Rectangle(x + padding, y + padding, width - padding * 2, height - padding * 2);
    }

    public boolean intersects(GameObject other) {
        if (other instanceof Tank) {
            // 坦克之间的碰撞使用较小的碰撞区域
            return this.getCollisionBounds().intersects(((Tank) other).getCollisionBounds());
        } else if (other instanceof Wall) {
            // 与墙壁的碰撞也使用较小的碰撞区域
            Rectangle wallBounds = new Rectangle(other.getX(), other.getY(), other.width, other.height);
            return this.getCollisionBounds().intersects(wallBounds);
        }
        // 其他情况使用默认的碰撞检测
        return super.intersects(other);
    }

    // Getter 和 Setter
    public Direction getDirection() {
        return direction;
    }

    public void setDirection(Direction direction) {
        this.direction = direction;
    }

    public boolean isMoving() {
        return moving;
    }

    public void setMoving(boolean moving) {
        this.moving = moving;
    }

    public boolean isPlayer() {
        return player;
    }
    
    public int getHealth() {
        return health;
    }
    
    public int getMaxHealth() {
        return maxHealth;
    }

    public void setHealth(int health) {
        this.health = health;
    }

    public boolean isActive() {
        return active;
    }

    public void setActive(boolean active) {
        this.active = active;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public int getWidth() {
        return width;
    }
}
